﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;

namespace UCF.Core
{
    /// <summary>
    /// Dll加载器
    /// <para>用于插件式开发中的热加载技术</para>
    /// </summary>
    /// <remarks>2014-4-3 1.0 by sutroon</remarks>
    public class DllLoader
    {
        /// <summary>
        /// 获取或设置应用程序启动目录
        /// </summary>
        public static string ApplicationStartupPath { get; set; }


        /// <summary>
        /// 设置决定路径
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static string SetAbsolutePath(string path)
        {
            if (Path.IsPathRooted(path) || string.IsNullOrEmpty(ApplicationStartupPath)) return path;
            return ApplicationStartupPath + "\\" + path;
        }

        /// <summary>
        /// 设置命名空间
        /// </summary>
        /// <param name="dllpath"></param>
        /// <param name="typename"></param>
        /// <returns></returns>
        public static string SetNamespace(string dllpath, string typename)
        {
            string ns = Path.GetFileNameWithoutExtension(dllpath);
            return typename.Contains('.') ? typename : ns + "." + typename;
        }

        /// <summary>
        /// 从文件中获取指定名称的类型
        /// </summary>
        /// <param name="dllpath"></param>
        /// <param name="typename"></param>
        /// <returns></returns>
        public static Type GetTypeFromFile(string dllpath, string typename)
        {
            dllpath = SetAbsolutePath(dllpath);
            if (!File.Exists(dllpath)) return null;

            typename = SetNamespace(dllpath, typename);

            try
            {
                Assembly assemly = Assembly.LoadFile(dllpath);
                return assemly.GetType(typename, true, true);
            }
            catch (ArgumentException)
            {
                throw;
            }
            catch (TypeLoadException)
            {
                throw;
            }
            catch (FileNotFoundException)
            {
                throw;
            }
            catch (FileLoadException)
            {
                throw;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 判断是否是有效的类型
        /// <para>无效类型包括：null | Exception</para>
        /// </summary>
        /// <param name="o"></param>
        /// <returns></returns>
        public static bool IsValidType(object o)
        {
            return !(o == null || o is Exception);
        }
    }
}
